package ide.ccf.ccproject.managedbuilder;

import ide.ccf.ccproject.translate.Message;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.SortedMap;

import org.eclipse.cdt.internal.ui.wizards.ICDTCommonProjectWizard;
import org.eclipse.cdt.managedbuilder.buildproperties.IBuildPropertyManager;
import org.eclipse.cdt.managedbuilder.buildproperties.IBuildPropertyType;
import org.eclipse.cdt.managedbuilder.buildproperties.IBuildPropertyValue;
import org.eclipse.cdt.managedbuilder.core.BuildListComparator;
import org.eclipse.cdt.managedbuilder.core.IInputType;
import org.eclipse.cdt.managedbuilder.core.IProjectType;
import org.eclipse.cdt.managedbuilder.core.ITool;
import org.eclipse.cdt.managedbuilder.core.IToolChain;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.ui.CDTSharedImages;
import org.eclipse.cdt.ui.newui.CDTPrefUtil;
import org.eclipse.cdt.ui.wizards.CNewWizard;
import org.eclipse.cdt.ui.wizards.EntryDescriptor;
import org.eclipse.cdt.ui.wizards.IWizardItemsListListener;
import org.eclipse.jface.wizard.IWizard;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;

public class ManagedBuildWizard extends CNewWizard {
	protected Composite parent;
	protected IWizardItemsListListener listener;
	private static final Image IMG = CDTSharedImages.getImage(CDTSharedImages.IMG_OBJS_CONTAINER);
	public static final String OTHERS_LABEL = "Others"; 
	public static boolean isCCFCatagory = false;
	

	@Override
	public EntryDescriptor[] createItems(boolean supportedOnly, IWizard wizard) {
		// TODO Auto-generated method stub
		if(isCCFCatagory == true)
		{
			IBuildPropertyManager bpm = ManagedBuildManager.getBuildPropertyManager();
			IBuildPropertyType bpt = bpm.getPropertyType(MbsWizardHandler.ARTIFACT);
			IBuildPropertyValue[] vs = bpt.getSupportedValues();
			Arrays.sort(vs, BuildListComparator.getInstance());
			
			ArrayList<EntryDescriptor> items = new ArrayList<EntryDescriptor>();
			// new style project types
			for (int i=0; i<vs.length; i++) {
				IToolChain[] tcs = ManagedBuildManager.getExtensionsToolChains(MbsWizardHandler.ARTIFACT, vs[i].getId(), false);
				if (tcs == null || tcs.length == 0) continue;
				MbsWizardHandler h = new MbsWizardHandler(vs[i], parent, wizard);
				for (int j=0; j<tcs.length; j++) {
					if (isValid(tcs[j], supportedOnly, wizard)) 
						h.addTc(tcs[j]);
				}
				if (h.getToolChainsCount() > 0) {
					// The project category item.
					items.add(new EntryDescriptor(vs[i].getId(), null, vs[i].getName(), true, h, null));
					// A default project type for that category -- not using any template.
					EntryDescriptor entryDescriptor = new EntryDescriptor(vs[i].getId() + ".default", vs[i].getId(), //$NON-NLS-1$
							Message.CCFMainWizardPage_DefaultProjectType, false, h, null);
					entryDescriptor.setDefaultForCategory(true);
					items.add(entryDescriptor);
				}
			}
			
			// old style project types
			EntryDescriptor oldsRoot = null;
			SortedMap<String, IProjectType> sm = ManagedBuildManager.getExtensionProjectTypeMap();
			for (String s : sm.keySet()) {
				IProjectType pt = sm.get(s);
				if (pt.isAbstract() || pt.isSystemObject()) continue;
				if (supportedOnly && !pt.isSupported()) continue; // not supported
				String nattr = pt.getNameAttribute(); 
				if (nattr == null || nattr.length() == 0) continue; // new proj style 
				MbsWizardHandler h = new MbsWizardHandler(pt, parent, wizard);
				IToolChain[] tcs = ManagedBuildManager.getExtensionToolChains(pt);
				for(int i = 0; i < tcs.length; i++){
					IToolChain t = tcs[i];
					if(t.isSystemObject()) 
						continue;
					if (!isValid(t, supportedOnly, wizard))
						continue;
					
					h.addTc(t);
				}
//				IConfiguration[] cfgs = pt.getConfigurations();
//				if (cfgs == null || cfgs.length == 0) continue;
//				IToolChain tc = null;
//				for (int i=0; i<cfgs.length; i++) {
//					if (cfgs[i].isSystemObject()) continue;
//					IToolChain t = cfgs[i].getToolChain();
//					if (isValid(t, supportedOnly, wizard)) {
//						tc = t;
//						break;
//					}
//				}
//				if (tc ==  null) continue;
//				h.addTc(tc);

				String pId = null;
				if (CDTPrefUtil.getBool(CDTPrefUtil.KEY_OTHERS)) {
					if (oldsRoot == null) {
						oldsRoot = new EntryDescriptor(OTHERS_LABEL, null, OTHERS_LABEL, true, null, null);
						//items.add(oldsRoot);
					}
					pId = oldsRoot.getId();
				} else {
					// do not group to <Others> - pId = null;
				}
				items.add(new EntryDescriptor(pt.getId(), pId, pt.getName(), false, h, IMG));
			}
			//isCCFCatagory = false;
			return items.toArray(new EntryDescriptor[items.size()]);
		}
		else
			return new EntryDescriptor[]{};
	}
	
	@Override
	public void setDependentControl(Composite _parent, IWizardItemsListListener _listener)
	{
		parent = _parent;
		listener = _listener;
	}
	
	/**
	 * Checks whether toolchain can be displayed 
	 * @param tc
	 * @return
	 */
	protected boolean isValid(IToolChain tc, boolean supportedOnly, IWizard w) {
		// Check for langiuage compatibility first in any case
		if (!isLanguageCompatible(tc, w))
			return false;
		
		// Do not do further check if all toolchains are permitted	
		if (!supportedOnly) 
			return true;
		
		// Filter off unsupported and system toolchains
		if (tc == null || !tc.isSupported() || tc.isAbstract() || tc.isSystemObject()) 
			return false;
		
		// Check for platform compatibility
		return ManagedBuildManager.isPlatformOk(tc);
	}

	/**
	 * Checks toolchain for Language ID, Content type ID 
	 * and Extensions, if they are required by wizard.
	 * 
	 * @param tc - toolchain to check
	 * @param w - wizard which provides selection criteria
	 * @return
	 */
	protected boolean isLanguageCompatible(IToolChain tc, IWizard w) {
		if (w == null) 
			return true;
		if (!(w instanceof ICDTCommonProjectWizard))
			return true;

		ITool[] tools = tc.getTools(); 
		ICDTCommonProjectWizard wz = (ICDTCommonProjectWizard)w;
		String[] langIDs = wz.getLanguageIDs(); 
		String[] ctypeIDs = wz.getContentTypeIDs();
		String[] exts = wz.getExtensions();
		
		// nothing requied ?   
		if (empty(langIDs) && empty(ctypeIDs) && empty(exts))
			return true;
		
		for (int i=0; i<tools.length; i++) {
			IInputType[] its = tools[i].getInputTypes();
			
			// no input types - check only extensions
			if (empty(its)) {  
				if (!empty(exts)) {
					String[] s = tools[i].getAllInputExtensions();
					if (contains(exts, s))
						return true; // extension fits
				}
				continue;
			}
			// normal tool with existing input type(s)
			for (int j = 0; j<its.length; j++) {
				// Check language IDs
				if (!empty(langIDs)) {
					String lang = its[j].getLanguageId(tools[i]);
					if (contains(langIDs, new String[] {lang})) {
						return true; // Language ID fits
					}
				}
				// Check content types
				if (!empty(ctypeIDs)) {
					String[] ct1 = its[j].getSourceContentTypeIds();
					String[] ct2 = its[j].getHeaderContentTypeIds();
					if (contains(ctypeIDs, ct1) ||
						contains(ctypeIDs, ct2)) 
					{
						return true; // content type fits
					}
				}					
				// Check extensions
				if (!empty(exts)) {
					String[] ex1 =its[j].getHeaderExtensions(tools[i]);
					String[] ex2 =its[j].getSourceExtensions(tools[i]);
					if (contains(exts, ex1) ||
						contains(exts, ex2)) {
						return true; // extension fits fits
					}
				}
			}
		}
		return false; // no one value fits to required
	}
	
	private boolean empty(Object[] s) {
		return (s == null || s.length == 0);
	}
	
	private boolean contains(String[] s1, String[] s2) {
		for (int i=0; i<s1.length; i++) 
			for (int j=0; j<s2.length; j++) 
				if (s1[i].equals(s2[j])) 
					return true;
		return false;
	}

}
